Ce tutorial présente une approche progressive pour créer un menu console en C#, en partant d'une version très simple jusqu'à une version interactive avec navigation au clavier.
Nous allons créer le menu principal d'un jeu vidéo fictif avec les options suivantes :
À travers 4 étapes progressives, vous apprendrez à :
Console.Write et Console.ReadLineMenu_Créer un menu simple en utilisant uniquement Console.WriteLine et Console.ReadLine.

Créez un nouveau projet Console App dans Visual Studio nommé GameMenu.
Adapter le contenu de Program.cs avec la proposition suivante :
Console.WriteLine("=== SUPER GAME ===");
Console.WriteLine("");
Console.WriteLine("1. Play");
Console.WriteLine("2. Options");
Console.WriteLine("3. Highscores");
Console.WriteLine("4. Quit");
Console.WriteLine("");
Console.Write("Enter your choice (1-4): ");
string? input = Console.ReadLine();
if (input == "1")
{
Console.WriteLine("Starting game...");
}
else if (input == "2")
{
Console.WriteLine("Opening options...");
}
else if (input == "3")
{
Console.WriteLine("Showing highscores...");
}
else if (input == "4")
{
Console.WriteLine("Goodbye!");
}
else
{
Console.WriteLine("Invalid choice!");
}
Console.ReadKey();
Lancer l'application et tester les différentes options.
Cette version fonctionne mais présente plusieurs problèmes :
WriteLine pour afficher une option)Adapter le code en utilisant l'instruction switch
Stocker les options dans un tableau pour centraliser les données et simplifier l'affichage.
Adapter le contenu de Program.cs selon la version suivante :
// Menu options stored in an array
string[] menuOptions = new string []{ "Play", "Options", "Highscores", "Quit" };
// Display title
Console.WriteLine("=== SUPER GAME ===");
Console.WriteLine("");
// Display menu options using a loop
for (int i = 0; i < menuOptions.Length; i++)
{
Console.WriteLine($"{i + 1}. {menuOptions[i]}");
}
Console.WriteLine("");
Console.Write($"Enter your choice (1-{menuOptions.Length}): ");
// Get user input
string? input = Console.ReadLine();
// Validate and process choice
if (int.TryParse(input, out int choice) && choice >= 1 && choice <= menuOptions.Length)
{
string selectedOption = menuOptions[choice - 1];
Console.WriteLine($"You selected: {selectedOption}");
// Handle the selection
switch (choice)
{
case 1:
Console.WriteLine("Starting game...");
break;
case 2:
Console.WriteLine("Opening options...");
break;
case 3:
Console.WriteLine("Showing highscores...");
break;
case 4:
Console.WriteLine("Goodbye!");
break;
}
}
else
{
Console.WriteLine("Invalid choice!");
}
Console.ReadKey();
Options écrites en dur | Options dans un tableau |
Boucle manuelle implicite | Boucle |
Validation manuelle |
|
Pour ajouter une nouvelle option, il suffit maintenant de modifier le tableau :
string[] menuOptions = { "Play", "Options", "Highscores", "Credits", "Quit" };
Organiser le code en fonctions préfixées par Menu_ pour une meilleure lisibilité et réutilisabilité.
Les fonctions permettent de :
Adapter le contenu de Program.cs selon la proposition suivante :
// Global array to store menu options
string[] options = Array.Empty<string>();
// Main program
Menu_Init();
Menu_Show();
int choice = Menu_GetUserChoice();
Menu_HandleChoice(choice);
Console.ReadKey();
// ============ MENU FUNCTIONS ============
void Menu_Init()
{
options = new string[] { "Play", "Options", "Highscores", "Quit" };
}
void Menu_AddOption(string option)
{
// Create a new array with one more slot
string[] newOptions = new string[options.Length + 1];
// Copy existing options
for (int i = 0; i < options.Length; i++)
{
newOptions[i] = options[i];
}
// Add new option at the end
newOptions[options.Length] = option;
// Replace old array
options = newOptions;
}
void Menu_Show()
{
Console.Clear();
Console.WriteLine("=== SUPER GAME ===");
Console.WriteLine("");
for (int i = 0; i < options.Length; i++)
{
Console.WriteLine($" {i + 1}. {options[i]}");
}
Console.WriteLine("");
}
int Menu_GetUserChoice()
{
Console.Write($"Enter your choice (1-{options.Length}): ");
string? input = Console.ReadLine();
if (int.TryParse(input, out int choice) && choice >= 1 && choice <= options.Length)
{
return choice;
}
return -1; // Invalid choice
}
void Menu_HandleChoice(int choice)
{
if (choice == -1)
{
Console.WriteLine("Invalid choice!");
return;
}
string selectedOption = options[choice - 1];
Console.WriteLine($"You selected: {selectedOption}");
switch (selectedOption)
{
case "Play":
Console.WriteLine("Starting game...");
break;
case "Options":
Console.WriteLine("Opening options...");
break;
case "Highscores":
Console.WriteLine("Showing highscores...");
break;
case "Quit":
Console.WriteLine("Goodbye!");
break;
default:
Console.WriteLine($"Action for '{selectedOption}' not implemented.");
break;
}
}
| Initialise le tableau avec les options par défaut |
| Ajoute une option au menu |
| Affiche le menu à l'écran |
| Lit et valide le choix de l'utilisateur |
| Exécute l'action correspondant au choix |
En se basant sur la théorie du cours, simplifier le code lorsq'on ajoute une option au tableau... (Array.Resize et/ou Array.Copy)
Modifier le programme principal pour tester l'ajout d'options :
Menu_Init();
Menu_AddOption("Credits"); // Add a new option
Menu_AddOption("Tutorial"); // Add another option
Menu_Show();
int choice = Menu_GetUserChoice();
Menu_HandleChoice(choice);
Console.ReadKey();
Remplacer la saisie de numéro par une navigation avec les touches fléchées et une mise en surbrillance de l'option sélectionnée.

Adapter Program.cs comme suit :
// Global variables
string[] options = Array.Empty<string>();
int selectedIndex = 0;
// Main program
Menu_Init();
int choice = Menu_RunInteractive();
Menu_HandleChoice(choice);
Console.ReadKey();
// ============ MENU FUNCTIONS ============
void Menu_Init()
{
options = new string[] { "Play", "Options", "Highscores", "Quit" };
selectedIndex = 0;
}
void Menu_AddOption(string option)
{
string[] newOptions = new string[options.Length + 1];
for (int i = 0; i < options.Length; i++)
{
newOptions[i] = options[i];
}
newOptions[options.Length] = option;
options = newOptions;
}
void Menu_ShowInteractive()
{
Console.Clear();
Console.WriteLine("=== SUPER GAME ===");
Console.WriteLine("");
Console.WriteLine("Use ↑↓ arrows to navigate, Enter to select");
Console.WriteLine("");
for (int i = 0; i < options.Length; i++)
{
if (i == selectedIndex)
{
// Highlight selected option
Console.BackgroundColor = ConsoleColor.White;
Console.ForegroundColor = ConsoleColor.Black;
Console.WriteLine($" > {options[i]} < ");
Console.ResetColor();
}
else
{
Console.WriteLine($" {options[i]} ");
}
}
Console.WriteLine("");
}
int Menu_RunInteractive()
{
ConsoleKey key;
do
{
Menu_ShowInteractive();
// Read key without displaying it
ConsoleKeyInfo keyInfo = Console.ReadKey(true);
key = keyInfo.Key;
// Handle navigation
if (key == ConsoleKey.UpArrow)
{
selectedIndex--;
if (selectedIndex < 0)
{
selectedIndex = options.Length - 1; // Wrap to bottom
}
}
else if (key == ConsoleKey.DownArrow)
{
selectedIndex++;
if (selectedIndex >= options.Length)
{
selectedIndex = 0; // Wrap to top
}
}
} while (key != ConsoleKey.Enter);
return selectedIndex + 1; // Return 1-based choice
}
int Menu_GetUserChoice()
{
Console.Write($"Enter your choice (1-{options.Length}): ");
string? input = Console.ReadLine();
if (int.TryParse(input, out int choice) && choice >= 1 && choice <= options.Length)
{
return choice;
}
return -1;
}
void Menu_HandleChoice(int choice)
{
if (choice == -1 || choice < 1 || choice > options.Length)
{
Console.WriteLine("Invalid choice!");
return;
}
string selectedOption = options[choice - 1];
Console.Clear();
Console.WriteLine($">>> {selectedOption.ToUpper()} <<<");
Console.WriteLine("");
switch (selectedOption)
{
case "Play":
Console.WriteLine("Starting game...");
Console.WriteLine("Loading level 1...");
break;
case "Options":
Console.WriteLine("=== OPTIONS ===");
Console.WriteLine("Sound: ON");
Console.WriteLine("Music: ON");
Console.WriteLine("Difficulty: Normal");
break;
case "Highscores":
Console.WriteLine("=== HIGHSCORES ===");
Console.WriteLine("1. AAA - 10000");
Console.WriteLine("2. BBB - 8500");
Console.WriteLine("3. CCC - 7200");
break;
case "Quit":
Console.WriteLine("Thanks for playing!");
Console.WriteLine("Goodbye!");
break;
default:
Console.WriteLine($"Action for '{selectedOption}' not implemented.");
break;
}
}
Le paramètre true empêche l'affichage du caractère saisi :
ConsoleKeyInfo keyInfo = Console.ReadKey(true);
Console.BackgroundColor = ConsoleColor.White;
Console.ForegroundColor = ConsoleColor.Black;
Console.WriteLine("Texte en surbrillance");
Console.ResetColor(); // Important : remettre les couleurs par défaut
// En haut de la liste, aller en bas
if (selectedIndex < 0)
{
selectedIndex = options.Length - 1;
}
// En bas de la liste, aller en haut
if (selectedIndex >= options.Length)
{
selectedIndex = 0;
}
Voici quelques améliorations à implémenter :
// Play a beep when navigating
Console.Beep(800, 50); // frequency, duration in ms
void Menu_SetColors(ConsoleColor background, ConsoleColor foreground)
{
Console.BackgroundColor = background;
Console.ForegroundColor = foreground;
}
void Menu_ShowTitle()
{
Console.WriteLine(@"
_____ _ _ _____ ______ _____
/ ____| | | | __ \| ____| __ \
| (___ | | | | |__) | |__ | |__) |
\___ \| | | | ___/| __| | _ /
____) | |__| | | | |____| | \ \
|_____/ \____/|_| |______|_| \_\
_____ __ __ ______
/ ____| /\ | \/ | ____|
| | __ / \ | \ / | |__
| | |_ | / /\ \ | |\/| | __|
| |__| |/ ____ \| | | | |____
\_____/_/ \_\_| |_|______|
");
}
bool running = true;
while (running)
{
Menu_Init();
int choice = Menu_RunInteractive();
if (options[choice - 1] == "Quit")
{
running = false;
}
else
{
Menu_HandleChoice(choice);
Console.WriteLine("\nPress any key to return to menu...");
Console.ReadKey(true);
}
}
1 | Console.Write/Read | Simple, direct |
2 | Tableau | Centralisation des données |
3 | Fonctions Menu_ | Organisation, réutilisabilité |
4 | Navigation clavier | Expérience utilisateur |
Ce code est prêt pour être transformé en classe...
// Les fonctions Menu_* deviendront des méthodes
// Les variables globales deviendront des attributs
public class Menu
{
private string[] options;
private int selectedIndex;
public void Init() { ... }
public void AddOption(string option) { ... }
public void Show() { ... }
public int GetUserChoice() { ... }
// etc.
}